home *** CD-ROM | disk | FTP | other *** search
- Unit ExtArray; {Extended Generic Fully-Dynamic Arrays}
- {$R-,O+,V-,S-}
-
- { The ExtendedArray is closely related to the MaxArray, but is limited only }
- { by your available diskspace. HOWEVER, Random access performance can only }
- { be described as AWFUL! Sequential and nearly-sequential access times are }
- { quite good (only off the standard array by a small constant), but random }
- { access is terrible. This is due to the way the array is stored on disk. }
-
- { The idea behind the Extended array is simple. Divide the array into a }
- { number of "Lobes", and then store these lobes on disk. Keep several of }
- { them on the Heap at all times, and simply swap lobes to and from disk as }
- { required. This is why sequential access is so good. Unfortunately, as }
- { the total number of lobes goes up, the chances of finding the indexed }
- { element on the Heap go down, causing the Extended Array to spend (MUCH) }
- { time swapping lobes back and forth (in the Random-Access case). }
-
- { Without doing the appropriate performance analyses, I can not say for }
- { sure how rapidly the performance degrades, but I have done sufficient }
- { testing to make a "seat-of-the-pants" analysis which indicates (to me) }
- { that it is best to keep Extended Arrays (which need a lot of random }
- { accessing) to approximately one-half on disk and one-half on the Heap. }
- { As the AutoInit method attempts to keep about 300k bytes of the Array on }
- { the Heap, My guess-work says that for arrays of up to about 600-700kbytes }
- { byte size, random performance should be satisfactory. Using the other }
- { initialization method (ManualInit), you can force the Heap portion of the }
- { Array up to 500k bytes, which should yield good performance for sizes up }
- { to 1.0 million bytes. }
-
- { NOTE: As with MaxArrays, ExtendedArrays are Indexed 0..MaxSize-1 }
-
- { All resemblance to MaxArray methods is Entirely intended! }
-
- INTERFACE
-
- Uses X_Table,FlexPntr;
-
- Type
- ExtendedArray = Object
-
- ElSize : Word;
- MaxEl : LongInt;
- WorkSpace : FlexPtr; {Currently useable Lobe provided by ExtendedTable}
- Lobes : Word;
- BuffSize : Word;
- Table : ExtendedTable;
- Current : Word; {Index of WorkSpace Lobe}
-
- Procedure Create;
-
- Procedure AutoInit (MaxElements : LongInt; ElementSize : Word);
-
- Procedure ManualInit (MaxElements : LongInt; ElementSize : Word;
- MaxLobeSize : Word);
- Procedure Destroy;
-
- Procedure Accept (Var El; Index : LongInt; Size : Word);
- {Assign the Indexth El}
-
- Procedure Retrieve (Var El; Index : LongInt; Size : Word);
- {Get the Indexth El}
-
- Procedure Copy (From : ExtendedArray);
- {Target *MUST* already be initialized}
- {to the EXACT same parameters as From}
- {this will save checking for sufficent}
- {available Memory!}
-
-
- Procedure Swap (I,J : LongInt); {Swap the Ith and Jth Elements}
-
- Function MaxSize : LongInt; {Report Array Length}
- Function ElemSize : Word; {Report Element Size}
-
- End;
-
- IMPLEMENTATION
-
- Procedure ExtendedArrayError (Num : Byte);
- Begin
- WriteLn;
- Write ('ExtendedArray ERROR: ');
- Case Num of
- 0 : WriteLn ('Attempted Init on Un-Created or Initialized ExtendedArray.');
- 2 : WriteLn ('Attempted Accept with Incorrect Size Variable.');
- 3 : WriteLn ('Attempted Accept on Un-Initialized ExtendedArray.');
- 4 : WriteLn ('Attempted Retrieve with Incorrect Size Variable.');
- 5 : WriteLn ('Attempted Retrieve with Un-Initialized ExtendedArray.');
- 6 : WriteLn ('***** INDEX OUT OF BOUNDS *****');
- 7 : WriteLn ('Attempted Copy on Un-Created or Initialized ExtendedArray.');
- 11 : WriteLn ('Insufficent Memory to perform Swap operation.');
- 12 : WriteLn ('Attempted Illegal Copy operation.');
- 13 : WriteLn ('Selected LobeSize is Too Large.');
- End;
- WriteLn ('**** PROGRAM TERMINATED ****');
- WriteLn;
- Write ('Press <Return> to Continue.... ');
- ReadLn;
- HALT (0)
- End;
-
- Procedure ExtendedArray.Create;
- Begin
- Table.Create;
- WorkSpace := Nil;
- ElSize := 0;
- MaxEl := 0;
- Lobes := 0;
- BuffSize := 0;
- End;
-
- Procedure ExtendedArray.AutoInit (MaxElements : LongInt; ElementSize : Word);
- Var
- NumLobes : Word;
- Begin
- NumLobes := 8;
- While ((MaxElements*ElementSize) Div NumLobes) > 37500 {keeps Heap to < 350k}
- do NumLobes := NumLobes + 1;
- BuffSize := ((MaxElements*ElementSize) Div NumLobes);
- BuffSize := BuffSize - (BuffSize Mod ElementSize);
- While LongInt(BuffSize * LongInt (NumLobes)) <
- LongInt(MaxElements * LongInt (ElementSize))
- do BuffSize := BuffSize + ElementSize;
- Lobes := NumLobes;
- Current := Lobes+1;
- Table.Init (NumLobes,BuffSize);
- ElSize := ElementSize;
- MaxEl := MaxElements
- End;
-
- Procedure ExtendedArray.ManualInit (MaxElements : LongInt; ElementSize : Word;
- MaxLobeSize : Word);
- Var
- NumLobes : Word;
- Temp : LongInt;
- Begin
- NumLobes := 8;
- While ((MaxElements*ElementSize) Div NumLobes) > MaxLobeSize
- do NumLobes := NumLobes + 1;
- Temp := ((MaxElements*ElementSize) Div NumLobes);
- Temp := Temp - (Temp Mod ElementSize);
- While LongInt(Temp * LongInt (NumLobes)) <
- LongInt(MaxElements * LongInt (ElementSize))
- do Temp := Temp + ElementSize;
-
- If Temp > 65521 Then ExtendedArrayError (13);
- BuffSize := Word(Temp);
- Lobes := NumLobes;
- Current := Lobes+1;
- Table.Init (NumLobes,BuffSize);
- ElSize := ElementSize;
- MaxEl := MaxElements
- End;
-
- Function ExtendedArray.MaxSize : LongInt;
- Begin
- MaxSize := MaxEl
- End;
-
- Function ExtendedArray.ElemSize : Word;
- Begin
- ElemSize := ElSize
- End;
-
- Procedure ExtendedArray.Destroy;
- Begin
- Table.Destroy;
- WorkSpace := Nil;
- ElSize := 0;
- MaxEl := 0;
- Lobes := 0;
- BuffSize := 0;
- End;
-
- Procedure Map (E : ExtendedArray; Index : LongInt; Var N : LongInt; Var K : Word);
- Var
- I : Word;
- J : LongInt;
- Begin
- I := 0;
- J := Index;
- While J >= E.BuffSize do
- Begin
- J := J-E.BuffSize;
- I := I + 1
- End;
- K := I;
- N := Word(J)
- End;
-
- Procedure ExtendedArray.Accept (Var El; Index : LongInt; Size : Word);
- Var
- I : Word;
- J : LongInt;
- Temp : FlexSpace Absolute El;
- Begin
- If Index >= MaxEl Then ExtendedArrayError (6);
- J := Index*ElSize; {Compute Actual Index}
- Map (Self,J,J,I);
-
- If I <> Current Then
- Begin
- WorkSpace := Table.Retrieve (I);
- Current := I
- End;
-
- If WorkSpace <> Nil
- Then
- If Size = ElSize
- Then
- Begin
- Move (Temp,WorkSpace^.Flex[J],ElSize);
- If Current <> I Then
- Table.Update (I,WorkSpace)
- End
- Else
- ExtendedArrayError (2)
- Else
- ExtendedArrayError (3)
- End;
-
- Procedure ExtendedArray.Retrieve (Var El; Index : LongInt; Size : Word);
- Var
- I : Word;
- J : LongInt;
- Temp : FlexSpace Absolute El;
- Begin
- If Index >= MaxEl Then ExtendedArrayError (6);
- J := Index*ElSize;
- Map (Self,J,J,I);
-
- If I <> Current Then
- Begin
- WorkSpace := Table.Retrieve (I);
- Current := I
- End;
-
- If WorkSpace <> Nil
- Then
- If Size = ElSize
- Then
- Move (WorkSpace^.Flex[J],Temp,ElSize)
- Else
- ExtendedArrayError (4)
- Else
- ExtendedArrayError (5)
- End;
-
- Procedure ExtendedArray.Copy (From : ExtendedArray);
- Var
- I : Word;
- Begin
- If (From.ElSize <> ElSize) or (From.MaxEl <> MaxEl) or (Lobes <> From.Lobes)
- Then ExtendedArrayError (12);
- For I := 0 to Lobes do
- Begin
- WorkSpace := From.Table.Retrieve (I);
- Table.Update (I,WorkSpace)
- End
- End;
-
- Procedure ExtendedArray.Swap (I,J : LongInt);
- Var
- Ith : FlexPtr;
- Jth : FlexPtr;
- Begin
- GetMem (Ith,SizeOf(FlexCount) + ElemSize);
- GetMem (Jth,SizeOf(FlexCount) + ElemSize);
- If (Ith = Nil) or (Jth = Nil) Then ExtendedArrayError(11);
- Retrieve (Ith^.Flex,I,ElemSize);
- Retrieve (Jth^.Flex,J,ElemSize);
- Accept (Ith^.Flex,J,ElemSize);
- Accept (Jth^.Flex,I,ElemSize);
- FreeMem (Ith,SizeOf(FlexCount) + ElemSize);
- FreeMem (Jth,SizeOf(FlexCount) + ElemSize)
- End;
-
- BEGIN
- HeapError := @HeapErrorTrap {Exported from FlexPntr}
- END.